package com.beney.client.handler;

import com.beney.client.Client;
import com.beney.codec.MessagePacket;
import com.beney.message.idle.HearbeatReq;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 处理客户端 channel 的异常
 */
@Component
@ChannelHandler.Sharable
public class ClientHandler extends ChannelInboundHandlerAdapter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private Client client;

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 和服务端断开了连接，所以需要重连
        logger.info("[channelInactive][连接断开]");
        client.reconnect();
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        logger.error("[exceptionCaught][连接 ({}) 发生异常]{}", ctx.channel().id(), cause.toString());
        // 断开连接
        ctx.channel().close();
    }

    /**
     * 与 IdleStateHandler 配合，在空闲一定时限的时候触发
     *
     * @param ctx ChannelHandlerContext
     * @param evt 事件
     * @throws Exception .
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // 超过空闲时限，发送一次心跳请求
        if (evt instanceof IdleStateEvent) {
            logger.info("[userEventTriggered][空闲到达 timeout, 客户端发起心跳]");
            HearbeatReq hearbeatReq = new HearbeatReq();
            ctx.writeAndFlush(new MessagePacket(HearbeatReq.TYPE, hearbeatReq))
                    .addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
